package com.tuniu.agents.util;

import java.util.Map;

import org.springframework.http.HttpHeaders;
import org.springframework.web.multipart.MultipartFile;

/**
 * Http call manager interface
 */
public interface HttpManager {

    /**
     * Initiates a GET request and returns the deserialized object
     *
     * @param url      Request URL
     * @param request  Request parameters
     * @param response Response type
     * @param <T>      Response type
     * @return Deserialized response object
     */
    <T> T get(String url, Object request, Class<T> response);

    /**
     * Initiates a GET request and returns the deserialized object
     *
     * @param url      Request URL
     * @param request  Request parameters
     * @param response Response type
     * @param encode   Whether to Base64 encode the request parameters
     * @param <T>      Response type
     * @return Deserialized response object
     */
    <T> T get(String url, Object request, Class<T> response, boolean encode);

    /**
     * Initiates a GET request and returns the deserialized object
     *
     * @param url      Request URL
     * @param request  Request parameters
     * @param response Response type
     * @param encode   Whether to Base64 encode the request parameters
     * @param headers  Custom request headers
     * @param <T>      Response type
     * @return Deserialized response object
     */
    @Deprecated
    <T> T get(String url, Object request, Class<T> response, boolean encode, HttpHeaders headers);

    /**
     * Initiates a GET request and returns the deserialized object
     *
     * @param url      Request URL
     * @param request  Request parameters
     * @param response Response type
     * @param encode   Whether to Base64 encode the request parameters
     * @param headers  Custom request headers
     * @param <T>      Response type
     * @return Deserialized response object
     */
    <T> T get(String url, Object request, Class<T> response, boolean encode, Map<String, String> headers);

    /**
     * Initiates a GET request and decodes Base64 response
     *
     * @param url      Request URL
     * @param request  Request parameters
     * @param response Response type
     * @param encode   Whether to Base64 encode the request parameters
     * @param <T>      Response type
     * @return Deserialized response object
     */
    <T> T getWithBase64Response(String url, Object request, Class<T> response, boolean encode);

    /**
     * Initiates a GET request and decodes Base64 response
     *
     * @param url      Request URL
     * @param request  Request parameters
     * @param response Response type
     * @param encode   Whether to Base64 encode the request parameters
     * @param headers  Custom request headers
     * @param <T>      Response type
     * @return Deserialized response object
     */
    @Deprecated
    <T> T getWithBase64Response(String url, Object request, Class<T> response, boolean encode, HttpHeaders headers);

    /**
     * Initiates a GET request and decodes Base64 response
     *
     * @param url      Request URL
     * @param request  Request parameters
     * @param response Response type
     * @param encode   Whether to Base64 encode the request parameters
     * @param headers  Custom request headers
     * @param <T>      Response type
     * @return Deserialized response object
     */
    <T> T getWithBase64Response(String url, Object request, Class<T> response, boolean encode, Map<String, String> headers);

    /**
     * Initiates a GET request, allowing both parameters and responses to be optionally Base64 encoded/decoded
     *
     * @param url            Request URL
     * @param request        Request parameters
     * @param response       Response type
     * @param encodeParams   Whether to Base64 encode the request parameters
     * @param decodeResponse Whether to Base64 decode the response
     * @param <T>            Response type
     * @return Deserialized response object
     */
    <T> T get(String url, Object request, Class<T> response, boolean encodeParams, boolean decodeResponse);

    /**
     * Initiates a GET request, allowing both parameters and responses to be optionally Base64 encoded/decoded
     *
     * @param url            Request URL
     * @param request        Request parameters
     * @param response       Response type
     * @param encodeParams   Whether to Base64 encode the request parameters
     * @param decodeResponse Whether to Base64 decode the response
     * @param headers        Custom request headers
     * @param <T>            Response type
     * @return Deserialized response object
     */
    @Deprecated
    <T> T get(String url, Object request, Class<T> response, boolean encodeParams, boolean decodeResponse, HttpHeaders headers);

    /**
     * Initiates a GET request, allowing both parameters and responses to be optionally Base64 encoded/decoded
     *
     * @param url            Request URL
     * @param request        Request parameters
     * @param response       Response type
     * @param encodeParams   Whether to Base64 encode the request parameters
     * @param decodeResponse Whether to Base64 decode the response
     * @param headers        Custom request headers
     * @param <T>            Response type
     * @return Deserialized response object
     */
    <T> T get(String url, Object request, Class<T> response, boolean encodeParams, boolean decodeResponse, Map<String, String> headers);

    /**
     * Initiates a GET request using Base64 encoded request parameters
     *
     * @param url      Request URL
     * @param request  Request parameters
     * @param response Response type
     * @param <T>      Response type
     * @return Deserialized response object
     */
    <T> T getWithBase64Params(String url, Object request, Class<T> response);

    /**
     * Initiates a GET request using Base64 encoded request parameters and decodes Base64 response
     *
     * @param url      Request URL
     * @param request  Request parameters
     * @param response Response type
     * @param <T>      Response type
     * @return Deserialized response object
     */
    <T> T getWithBase64ParamsAndResponse(String url, Object request, Class<T> response);

    /**
     * Initiates a GET request using Base64 encoded request parameters and custom request headers
     *
     * @param url      Request URL
     * @param request  Request parameters
     * @param response Response type
     * @param headers  Custom request headers
     * @param <T>      Response type
     * @return Deserialized response object
     */
    @Deprecated
    <T> T getWithBase64Params(String url, Object request, Class<T> response, HttpHeaders headers);

    /**
     * Initiates a GET request using Base64 encoded request parameters and custom request headers
     *
     * @param url      Request URL
     * @param request  Request parameters
     * @param response Response type
     * @param headers  Custom request headers
     * @param <T>      Response type
     * @return Deserialized response object
     */
    <T> T getWithBase64Params(String url, Object request, Class<T> response, Map<String, String> headers);

    /**
     * Initiates a GET request using Base64 encoded request parameters and custom request headers, and decodes Base64 response
     *
     * @param url      Request URL
     * @param request  Request parameters
     * @param response Response type
     * @param headers  Custom request headers
     * @param <T>      Response type
     * @return Deserialized response object
     */
    @Deprecated
    <T> T getWithBase64ParamsAndResponse(String url, Object request, Class<T> response, HttpHeaders headers);

    /**
     * Initiates a GET request using Base64 encoded request parameters and custom request headers, and decodes Base64 response
     *
     * @param url      Request URL
     * @param request  Request parameters
     * @param response Response type
     * @param headers  Custom request headers
     * @param <T>      Response type
     * @return Deserialized response object
     */
    <T> T getWithBase64ParamsAndResponse(String url, Object request, Class<T> response, Map<String, String> headers);

    /**
     * Initiates a POST request and returns the deserialized object
     *
     * @param url          Request URL
     * @param request      Request body
     * @param responseType Response content type
     * @param <T>          Generic type
     * @return Deserialized response object
     */
    <T> T post(String url, Object request, Class<T> responseType);

    /**
     * Initiates a POST request and returns the deserialized object
     *
     * @param url          Request URL
     * @param request      Request body
     * @param responseType Response content type
     * @param headers      Custom request headers
     * @param <T>          Generic type
     * @return Deserialized response object
     */
    @Deprecated
    <T> T post(String url, Object request, Class<T> responseType, HttpHeaders headers);

    /**
     * Initiates a POST request and returns the deserialized object
     *
     * @param url          Request URL
     * @param request      Request body
     * @param responseType Response content type
     * @param headers      Custom request headers
     * @param <T>          Generic type
     * @return Deserialized response object
     */
    <T> T post(String url, Object request, Class<T> responseType, Map<String, String> headers);

    /**
     * Initiates a POST request and returns the deserialized object
     *
     * @param url            Request URL
     * @param request        Request body
     * @param responseType   Response content type
     * @param headers        Custom request headers
     * @param encodeBody     Whether to Base64 encode the request body
     * @param decodeResponse Whether to Base64 decode the response
     * @param <T>            Generic type
     * @return Deserialized response object
     */
    @Deprecated
    <T> T post(String url, Object request, Class<T> responseType, HttpHeaders headers, boolean encodeBody, boolean decodeResponse);

    /**
     * Initiates a POST request and returns the deserialized object
     *
     * @param url            Request URL
     * @param request        Request body
     * @param responseType   Response content type
     * @param headers        Custom request headers
     * @param encodeBody     Whether to Base64 encode the request body
     * @param decodeResponse Whether to Base64 decode the response
     * @param <T>            Generic type
     * @return Deserialized response object
     */
    <T> T post(String url, Object request, Class<T> responseType, Map<String, String> headers, boolean encodeBody, boolean decodeResponse);

    /**
     * Initiates a POST request using Base64 encoded request body
     *
     * @param url          Request URL
     * @param request      Request body
     * @param responseType Response content type
     * @param <T>          Generic type
     * @return Deserialized response object
     */
    <T> T postWithBase64Body(String url, Object request, Class<T> responseType);

    /**
     * Initiates a POST request using Base64 encoded request body and decodes Base64 response
     *
     * @param url          Request URL
     * @param request      Request body
     * @param responseType Response content type
     * @param <T>          Generic type
     * @return Deserialized response object
     */
    <T> T postWithBase64BodyAndResponse(String url, Object request, Class<T> responseType);

    /**
     * Initiates a POST request using Base64 encoded request body and custom request headers
     *
     * @param url          Request URL
     * @param request      Request body
     * @param responseType Response content type
     * @param headers      Custom request headers
     * @param <T>          Generic type
     * @return Deserialized response object
     */
    @Deprecated
    <T> T postWithBase64Body(String url, Object request, Class<T> responseType, HttpHeaders headers);

    /**
     * Initiates a POST request using Base64 encoded request body and custom request headers
     *
     * @param url          Request URL
     * @param request      Request body
     * @param responseType Response content type
     * @param headers      Custom request headers
     * @param <T>          Generic type
     * @return Deserialized response object
     */
    <T> T postWithBase64Body(String url, Object request, Class<T> responseType, Map<String, String> headers);

    /**
     * Initiates a POST request using Base64 encoded request body and custom request headers, and decodes Base64 response
     *
     * @param url          Request URL
     * @param request      Request body
     * @param responseType Response content type
     * @param headers      Custom request headers
     * @param <T>          Generic type
     * @return Deserialized response object
     */
    <T> T postWithBase64BodyAndResponse(String url, Object request, Class<T> responseType, Map<String, String> headers);

    /**
     * Sends a form formatted POST request
     * Content-Type is "application/x-www-form-urlencoded"
     *
     * @param url       Request URL
     * @param formData  Form data
     * @param responseType Response type
     * @param <T>      Response type generic
     * @return Response object
     */
    <T> T postForm(String url, Map<String, String> formData, Class<T> responseType);

    /**
     * Sends a form formatted POST request with custom request headers
     *
     * @param url       Request URL
     * @param formData  Form data
     * @param responseType Response type
     * @param headers   Request headers
     * @param <T>      Response type generic
     * @return Response object
     */
    <T> T postForm(String url, Map<String, String> formData, Class<T> responseType, HttpHeaders headers);

    /**
     * Sends a form formatted POST request with custom request headers, allowing optional Base64 response decoding
     *
     * @param url       Request URL
     * @param formData  Form data
     * @param responseType Response type
     * @param headers   Request headers
     * @param decodeResponse Whether to decode Base64 response
     * @param <T>      Response type generic
     * @return Response object
     */
    <T> T postForm(String url, Map<String, String> formData, Class<T> responseType, Map<String, String> headers, boolean decodeResponse);

    /**
     * Sends a form formatted POST request and decodes Base64 response
     *
     * @param url       Request URL
     * @param formData  Form data
     * @param responseType Response type
     * @param <T>      Response type generic
     * @return Response object
     */
    <T> T postFormWithBase64Response(String url, Map<String, String> formData, Class<T> responseType);

    /**
     * Sends a form formatted POST request with custom request headers and decodes Base64 response
     *
     * @param url       Request URL
     * @param formData  Form data
     * @param responseType Response type
     * @param headers   Request headers
     * @param <T>      Response type generic
     * @return Response object
     */
    <T> T postFormWithBase64Response(String url, Map<String, String> formData, Class<T> responseType, HttpHeaders headers);

    /**
     * Sends a form formatted POST request using an object as form data
     * The object will be converted to Map<String, String> format
     *
     * @param url       Request URL
     * @param formObject Form data object
     * @param responseType Response type
     * @param <T>      Response type generic
     * @return Response object
     */
    <T> T postFormObject(String url, Object formObject, Class<T> responseType);

    /**
     * Sends a form formatted POST request with custom request headers using an object as form data
     *
     * @param url       Request URL
     * @param formObject Form data object
     * @param responseType Response type
     * @param headers   Request headers
     * @param <T>      Response type generic
     * @return Response object
     */
    <T> T postFormObject(String url, Object formObject, Class<T> responseType, HttpHeaders headers);
    
    /**
     * Send a file upload POST request
     *
     * @param url             Request URL
     * @param formObject      Form data object
     * @param file          File data, key is field name, value is MultipartFile object
     * @param responseType    Response type
     * @param headers         Request headers
     * @param decodeResponse  Whether to decode Base64 response
     * @param <T>             Response type generic
     * @return Response object
     */
    <T> T postFileObject(String url, Object formObject, MultipartFile file, Class<T> responseType, Map<String, String> headers, boolean decodeResponse);
}